package com.north.light.librxffmpeg;

import android.content.Context;
import android.util.Log;

import com.north.light.librxffmpeg.bean.FFmpegVideoInfo;
import com.north.light.librxffmpeg.utils.LibFFmpegGsonUtils;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import io.microshow.rxffmpeg.RxFFmpegInvoke;

/**
 * author:li
 * date:2022/3/22
 * desc:ffmpeg功能类--提供外部调用方法
 */
public class FFmpegFunc implements FFmpegFuncApi {

    private static final class SingleHolder {
        private static final FFmpegFunc mInstance = new FFmpegFunc();
    }

    public static FFmpegFunc getInstance() {
        return SingleHolder.mInstance;
    }

    /**
     * 初始化
     */
    @Override
    public void init(Context context) {

    }

    /**
     * 获取视频信息--同步--权限交由外部监查
     *
     * @param path 路径
     */
    @Override
    public FFmpegVideoInfo getMediaInfo(String path) {
        String info = RxFFmpegInvoke.getInstance().getMediaInfo(path);
        if (info == null) {
            return null;
        }
        //转换数据
        String[] splitCacheArray = info.split(";");
        if (splitCacheArray.length == 0) {
            return null;
        }
        Map<String, String> trainMap = new HashMap<>();
        for (String cacheStr : splitCacheArray) {
            int equalPos = cacheStr.indexOf("=");
            if (equalPos == -1) {
                return null;
            }
            String key = cacheStr.substring(0, equalPos);
            String value = cacheStr.substring(equalPos + 1);
            trainMap.put(key, value);
        }
        String mapGsonStr = LibFFmpegGsonUtils.getJsonStr(trainMap);
        FFmpegVideoInfo videoInfo = null;
        try {
            videoInfo = LibFFmpegGsonUtils.getClassByStr(mapGsonStr, FFmpegVideoInfo.class);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return videoInfo;
    }

    @Override
    public void release() {
        RxFFmpegInvoke.getInstance().exit();
    }

    @Override
    public void crop(String path, String startTime, String duration, String outPath, FFmpegFunCallback listener) {
        String cmd = "ffmpeg -y -ss " + startTime + " -t " + duration + " -accurate_seek" + " -i " + path + " -codec copy -avoid_negative_ts 1 " + outPath;
        createFile(new File(outPath), true);
        String[] command = cmd.split(" ");
        RxFFmpegInvoke.getInstance().runCommandAsync(command, new RxFFmpegInvoke.IFFmpegListener() {
            @Override
            public void onFinish() {
                if (listener != null) {
                    listener.success(outPath);
                }
            }

            @Override
            public void onProgress(int progress, long progressTime) {

            }

            @Override
            public void onCancel() {
                if (listener != null) {
                    listener.cancel();
                }
            }

            @Override
            public void onError(String message) {
                if (listener != null) {
                    listener.failed(message);
                }
            }
        });
    }

    /**
     * 未调试--慎用
     */
    @Override
    public void compress(String path, String outPath, FFmpegFunCallback listener) {
        String cmd = "ffmpeg -y -threads 2 -i " + path + " -strict -2 -vcodec libx264 -preset ultrafast -crf 28 -acodec copy -ac 2 " + outPath;
        String[] command = cmd.split(" ");
        RxFFmpegInvoke.getInstance().runCommandAsync(command, new RxFFmpegInvoke.IFFmpegListener() {
            @Override
            public void onFinish() {
                if (listener != null) {
                    listener.success(outPath);
                }
            }

            @Override
            public void onProgress(int progress, long progressTime) {
                Log.e("FFmpegFunc", "onProgress：" + progress);
            }

            @Override
            public void onCancel() {
                if (listener != null) {
                    listener.cancel();
                }
            }

            @Override
            public void onError(String message) {
                if (listener != null) {
                    listener.failed(message);
                }
            }
        });
    }


    /**
     * 给视频增加图片
     *
     * @param videoFile   原视频完整路径
     * @param picturePath 图片完整路径
     * @param overX       图片的左上角 放到视频的X坐标
     * @param overY       图片的左上角 放到视频的X坐标
     * @return 返回目标文件
     */
    public String[] executeOverLayVideoFrame(String videoFile, String picturePath, String outPath, int overX, int overY) {
        String filter = String.format(Locale.getDefault(), "overlay=%d:%d", overX, overY);
        String cmd = "ffmpeg -y -threads 2 -i " + videoFile + " -i " + picturePath + " -filter_complex "
                + filter + " -preset superfast " + outPath;
        String[] command = cmd.split(" ");
        return command;
    }

    /**
     * 视频添加文字
     * ffmpeg -y -i /storage/emulated/0/1/input.mp4 -i /storage/emulated/0/1/input.png -filter_complex [0:v]scale=iw:ih[outv0];[1:0]scale=0.0:0.0[outv1];[outv0][outv1]overlay=0:0 -preset superfast /storage/emulated/0/1/result.mp4
     */
    @Override
    public void addTxt(String videoPath, String picPath, String outPath, FFmpegFunCallback listener) {
        //创建目标文件
        createFile(new File(outPath), true);
        String[] command = executeOverLayVideoFrame(videoPath, picPath, outPath, 0, 0);
        RxFFmpegInvoke.getInstance().runCommandAsync(command, new RxFFmpegInvoke.IFFmpegListener() {
            @Override
            public void onFinish() {
                if (listener != null) {
                    listener.success(outPath);
                }
            }

            @Override
            public void onProgress(int progress, long progressTime) {
                Log.e("FFmpegFunc addTxt", "onProgress：" + progress);
            }

            @Override
            public void onCancel() {
                if (listener != null) {
                    listener.cancel();
                }
            }

            @Override
            public void onError(String message) {
                if (listener != null) {
                    listener.failed(message);
                }
            }
        });
    }

    public static void createFile(File file, boolean isFile) {// 创建文件
        if (!file.exists()) {// 如果文件不存在
            if (!file.getParentFile().exists()) {// 如果文件父目录不存在
                createFile(file.getParentFile(), false);
            } else {// 存在文件父目录
                if (isFile) {// 创建文件
                    try {
                        file.createNewFile();// 创建新文件
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                } else {
                    file.mkdir();// 创建目录
                }
            }
        }
    }


}
